home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / unixcpio.gz / unixnet.cpio / telunix.c < prev    next >
C/C++ Source or Header  |  1994-07-11  |  7KB  |  344 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "config.h"
  4. #include "mbuf.h"
  5. #include "timer.h"
  6. #include "icmp.h"
  7. #include "netuser.h"
  8. #include "tcp.h"
  9. #include "telnet.h"
  10. #include "session.h"
  11.  
  12. #define TUMAXSCAN 3    /* max number of telunix clients active */
  13. #define TURQSIZ    512    /* max data we will request from pty at once */
  14.  
  15. struct tcb *tnix_tcb = NULLTCB;
  16. struct tcb *tnixtcb[TUMAXSCAN];    /* savebuf for tcb ptrs for scan routines */
  17. extern int errno;
  18.  
  19. /* Start telnet-unix server */
  20. tnix1(argc,argv)
  21. char *argv[];
  22. {
  23.     struct socket lsocket;
  24.     extern int32 ip_addr;
  25.     void tnix_state();
  26.  
  27.     /* Incoming Telnet */
  28.     lsocket.address = ip_addr;
  29.  
  30.     if(argc < 2)
  31.         lsocket.port = TELNET_PORT;
  32.     else
  33.         lsocket.port = atoi(argv[1]);
  34.  
  35.     tnix_tcb = open_tcp(&lsocket,NULLSOCK,TCP_SERVER,0,
  36.             NULLVFP,NULLVFP,tnix_state,0,(char *)NULL);
  37.  
  38.     if(tnix_tcb == NULLTCB)
  39.         fprintf(stderr,"start telunix fails rsn %d.\n",net_error);
  40.     else
  41.         log(tnix_tcb,"STARTED Telunix - (%d %x)",
  42.             lsocket.port,tnix_tcb);
  43. }
  44.  
  45. /* Shut down Telnet server */
  46. tnix0()
  47. {
  48.     if(tnix_tcb != NULLTCB) {
  49.         log(tnix_tcb,"STOPPED Telunix - (%x)",tnix_tcb);
  50.         close_tcp(tnix_tcb);
  51.     } else
  52.         fprintf(stderr,"stop telunix fails -- no server active.\n");
  53. }
  54.  
  55. /* Handle incoming Telnet-Unix connect requests */
  56. static void
  57. tnix_state(tcb,old,new)
  58. struct tcb *tcb;
  59. char old,new;
  60. {
  61.     register struct telnet *tn;
  62.     int tnix_addscan();
  63.     extern void tnix_rmvscan();
  64.     extern int send_tcp();
  65.     extern struct mbuf *free_p();
  66.     extern int del_tcp();
  67.     extern int close_tcp();
  68. #ifdef    SYS5
  69.     extern void free();
  70. #endif
  71.  
  72.     tn = (struct telnet *)tcb->user;
  73.  
  74.     switch(new){
  75.     case ESTABLISHED:
  76.         /* Create and initialize a Telnet protocol descriptor */
  77.         if((tn = (struct telnet *)calloc(1,sizeof(struct telnet))) == NULLTN){
  78.             log(tcb,"reject Telunix - no space");
  79.             sndmsg(tcb,"Rejected; no space on remote\n");
  80.             close_tcp(tcb);
  81.             return;
  82.         }
  83.         tn->session = NULLSESSION;
  84.         tn->state = TS_DATA;
  85.         tcb->user = (char *)tn;    /* Upward pointer */
  86.         tn->tcb = tcb;        /* Downward pointer */
  87.         tn->inbuf = NULLBUF;
  88.         tn->outbuf = NULLBUF;
  89.         if(tnix_addscan(tcb) < 0 ||
  90.            (tn->fd = OpenPty()) < 3) {    /* barf if <= stderr */
  91.             tnix_rmvscan(tcb);
  92.             log(tcb,"reject Telunix - no Unix ports");
  93.             sndmsg(tcb,
  94.                 "Rejected; no ports available on remote\n");
  95.             close_tcp(tcb);
  96.             return;
  97.         }
  98.         log(tcb,"open Telunix - (%d %x %d %d)",tn->fd,tcb,old,new);
  99.         break;
  100.  
  101.     case FINWAIT1:
  102.     case FINWAIT2:
  103.     case CLOSING:
  104.     case LAST_ACK:
  105.     case TIME_WAIT:
  106.         if(tn != NULLTN &&
  107.            tn->fd > 2) {
  108.             log(tcb,"close Telunix - (%d %x %d %d)",
  109.                 tn->fd,tcb,old,new);
  110.             close(tn->fd);
  111.             tn->fd = 0;
  112.         }
  113.         tnix_rmvscan(tcb);
  114.         break;
  115.  
  116.     case CLOSE_WAIT:
  117.         /* flush that last buffer */
  118.         if(tn != NULLTN &&
  119.            tn->outbuf != NULLBUF &&
  120.            tn->outbuf->cnt != 0) {
  121.             send_tcp(tcb,tn->outbuf);
  122.             tn->outbuf = NULLBUF;
  123.         }
  124.         close_tcp(tcb);
  125.         break;
  126.     
  127.     case CLOSED:
  128.         if(tn != NULLTN) {
  129.             if(tn->fd > 2) {
  130.                 log(tcb,"close Telunix - (%d %x %d %d)",
  131.                     tn->fd,tcb,old,new);
  132.                 close(tn->fd);
  133.                 tn->fd = 0;
  134.             }
  135.             if(tn->inbuf != NULLBUF)
  136.                 free_p(tn->inbuf);
  137.             if(tn->outbuf != NULLBUF)
  138.                 free_p(tn->outbuf);
  139.             free((char *)tn);
  140.         }
  141.         tnix_rmvscan(tcb);
  142.         del_tcp(tcb);
  143.         if(tcb == tnix_tcb)
  144.             tnix_tcb = NULLTCB;
  145.         break;
  146.     }
  147. }
  148.  
  149. /* Telunix io interface.  Called periodically to process any waiting io.  */
  150. void
  151. tnix_try(tcb)
  152. register struct tcb *tcb;
  153. {
  154.     extern void tnix_rmvscan();
  155.     extern int recv_tcp();
  156.     extern int send_tcp();
  157.     extern void tnix_input();
  158.  
  159.     register struct telnet *tn;
  160.     register int i;
  161.  
  162.     if((tn = (struct telnet *)tcb->user) == NULLTN || tn->fd < 3) {
  163.         /* Unknown connection - remove it from queue */
  164.         log(tcb,"error Telnet - tnix_try (%d)", tn);
  165.         tnix_rmvscan(tcb);
  166.         return;
  167.     }
  168.     /*
  169.      * First, check if there is any pending io for the pty:
  170.      */
  171.     if(tn->inbuf != NULLBUF) {
  172.         tnix_input(tn);
  173.     }
  174.     if(tn->inbuf == NULLBUF) {
  175.         if(tcb->rcvcnt > 0 &&
  176.            recv_tcp(tcb,&(tn->inbuf),0) > 0)
  177.             tnix_input(tn);
  178.     }
  179.     /*
  180.      * Next, check if there is any io for tcp:
  181.      */
  182.     do {
  183.         if(tn->outbuf == NULLBUF &&
  184.            (tn->outbuf = alloc_mbuf(TURQSIZ)) == NULLBUF)
  185.             return;        /* can't do much without a buffer */
  186.     
  187.         if(tn->outbuf->cnt < TURQSIZ) {
  188.             if((i = read(tn->fd, tn->outbuf->data + tn->outbuf->cnt,
  189.                 (int)(TURQSIZ - tn->outbuf->cnt))) == -1) {
  190.                 log(tcb,"error Telunix - read (%d %d %d)",
  191.                     errno, tn->fd,
  192.                     TURQSIZ - tn->outbuf->cnt);
  193.                 close_tcp(tcb);
  194.                 return;
  195.             }
  196.             if((tn->outbuf->cnt += i) < TURQSIZ)
  197.                 i = 0;    /* didn't fill buffer so don't retry */
  198.         } else {
  199.             i = -1;        /* any nonzero value will do */
  200.         }
  201.         if(tn->outbuf->cnt == 0 ||    /* nothing to send */
  202.            tcb->sndcnt > tcb->window)    /* too congested to send */
  203.             return;
  204.         if(send_tcp(tcb,tn->outbuf) < 0) {
  205.             log(tcb,"error Telunix - send_tcp (%d %d %d)",
  206.                 net_error, tn->fd, tn->outbuf->cnt);
  207.             close_tcp(tcb);
  208.             tn->outbuf = NULLBUF;
  209.             return;
  210.         }
  211.         tn->outbuf = NULLBUF;
  212.     } while(i);
  213. }
  214.  
  215. /* Process incoming TELNET characters */
  216. void
  217. tnix_input(tn)
  218. register struct telnet *tn;
  219. {
  220.     void doopt(),dontopt(),willopt(),wontopt(),answer();
  221.     char *memchr();
  222.     register int i;
  223.     register struct mbuf *bp;
  224.     char c;
  225.  
  226.     bp = tn->inbuf;
  227.  
  228.     /* Optimization for very common special case -- no special chars */
  229.     if(tn->state == TS_DATA){
  230.         while(bp != NULLBUF &&
  231.               memchr(bp->data,IAC,(int)bp->cnt) == NULLCHAR) {
  232.             if((i = write(tn->fd, bp->data, (int)bp->cnt)) == bp->cnt) {
  233.                 tn->inbuf = bp = free_mbuf(bp);
  234.             } else if(i == -1) {
  235.                 log(tn->tcb,"error Telunix - write (%d %d %d)",
  236.                     errno, tn->fd, bp->cnt);
  237.                 close_tcp(tn->tcb);
  238.                 return;
  239.             } else {
  240.                 bp->cnt -= i;
  241.                 bp->data += i;
  242.                 return;
  243.             }
  244.         }
  245.         if(bp == NULLBUF)
  246.             return;
  247.     }
  248.     while(pullup(&(tn->inbuf),&c,1) == 1){
  249.         bp = tn->inbuf;
  250.         switch(tn->state){
  251.         case TS_DATA:
  252.             if(uchar(c) == IAC){
  253.                 tn->state = TS_IAC;
  254.             } else {
  255.                 if(!tn->remote[TN_TRANSMIT_BINARY])
  256.                     c &= 0x7f;
  257.                 if(write(tn->fd, &c, 1) != 1) {
  258.                     /* we drop a character here */
  259.                     return;
  260.                 }
  261.             }
  262.             break;
  263.         case TS_IAC:
  264.             switch(uchar(c)){
  265.             case WILL:
  266.                 tn->state = TS_WILL;
  267.                 break;
  268.             case WONT:
  269.                 tn->state = TS_WONT;
  270.                 break;
  271.             case DO:
  272.                 tn->state = TS_DO;
  273.                 break;
  274.             case DONT:
  275.                 tn->state = TS_DONT;
  276.                 break;
  277.             case IAC:
  278.                 if(write(tn->fd, &c, 1) != 1) {
  279.                     /* we drop a character here */
  280.                     return;
  281.                 }
  282.                 tn->state = TS_DATA;
  283.                 break;
  284.             default:
  285.                 tn->state = TS_DATA;
  286.                 break;
  287.             }
  288.             break;
  289.         case TS_WILL:
  290.             willopt(tn,c);
  291.             tn->state = TS_DATA;
  292.             break;
  293.         case TS_WONT:
  294.             wontopt(tn,c);
  295.             tn->state = TS_DATA;
  296.             break;
  297.         case TS_DO:
  298.             doopt(tn,c);
  299.             tn->state = TS_DATA;
  300.             break;
  301.         case TS_DONT:
  302.             dontopt(tn,c);
  303.             tn->state = TS_DATA;
  304.             break;
  305.         }
  306.     }
  307. }
  308.  
  309. /* called periodically from main loop */
  310. void
  311. tnix_scan()
  312. {
  313.     void tnix_try();
  314.     register int i;
  315.  
  316.     for(i = 0; i < TUMAXSCAN; i += 1)
  317.         if(tnixtcb[i] != NULLTCB)
  318.             tnix_try(tnixtcb[i]);
  319. }
  320.  
  321. int
  322. tnix_addscan(tcb)
  323. struct tcb *tcb;
  324. {
  325.     register int i;
  326.     for(i = 0; i < TUMAXSCAN; i += 1)
  327.         if(tnixtcb[i] == NULLTCB) {
  328.             tnixtcb[i] = tcb;
  329.             return i;
  330.         }
  331.     return -1;
  332. }
  333.  
  334. void
  335. tnix_rmvscan(tcb)
  336. struct tcb *tcb;
  337. {
  338.     register int i;
  339.  
  340.     for(i = 0; i < TUMAXSCAN; i += 1)
  341.         if(tnixtcb[i] == tcb)
  342.             tnixtcb[i] = NULLTCB;
  343. }
  344.